package business.services;

import java.util.Date;
import java.util.List;
import java.util.Vector;

import data.entities.Cliente;
import data.entities.Ficha;
import data.entities.Socio;
import data.repository.IRepository;
import data.repository.QueryParameter;
import data.repository.Repository;
import data.repository.RepositoryException;
import business.interfaces.ICliente;
import business.interfaces.ISocio;

public class ServicioClientes implements IServicioClientes {
	private IRepository<Cliente> repositorioClientes;
	private IRepository<Ficha> repositorioCuentas;
	private IRepository<Socio> repositorioSocios;
	
	public ServicioClientes() {
		this.repositorioClientes = new Repository<Cliente>();
		this.repositorioCuentas = new Repository<Ficha>();
		this.repositorioSocios = new Repository<Socio>();
	}
	
	public List<ICliente> getClientes() throws ServiceException {
		List<Cliente> clientes;
		
		try {
			clientes = this.repositorioClientes.getAll(Cliente.class);
		} catch (RepositoryException e) {
			throw new ServiceException(e);
		}	
		
		List<ICliente> result = new Vector<ICliente>();
		
		for(Cliente cliente : clientes) {
			result.add(cliente);
		}
		
		return result;
	}

	public List<ISocio> getSocios() throws ServiceException {
		List<Socio> socios;
		
		try {
			socios = this.repositorioSocios.getAll(Socio.class);
		} catch (RepositoryException e) {
			throw new ServiceException(e);
		}	
		
		List<ISocio> result = new Vector<ISocio>();
		
		for(Socio socio : socios) {
			result.add(socio);
		}
		
		return result;
	}

	public ICliente getCliente(String dni) throws ServiceException {
		try {
			return this.getClienteExistente(dni);
		} catch (RepositoryException e) {
			throw new ServiceException(e);
		}
	}
	
	public ISocio getSocio(String dni) throws ServiceException {
		try {
			return this.getSocioExistente(dni);
		} catch (RepositoryException e) {
			throw new ServiceException(e);
		}
	}

	public Boolean esSocio(String dni) throws ServiceException {
		return this.getSocio(dni) != null;
	}

	public void registrarCliente(String dni, String nombre) throws ServiceException {
		try {
			Cliente clienteExistente = this.getClienteExistente(dni);
			
			if(clienteExistente != null) {
				String mensaje = String.format("El cliente %s ya existe y no puede ser modificado", dni);
				
				throw new ServiceException(mensaje);
			}
			
			Cliente newCliente = new Cliente();
			
			newCliente.setDni(dni);
			newCliente.setNombre(nombre);
		
			this.repositorioClientes.saveOrUpdate(newCliente);
		} catch (RepositoryException e) {
			throw new ServiceException(e);
		}
	}

	public void registrarSocio(String dni, String nombre, Date fechaNac,
			String domicilio, String telefono, String email) throws ServiceException {
		
		try {
			Socio socioExistente = this.getSocioExistente(dni);
			
			if(socioExistente != null) {
				String mensaje = String.format("El socio %s ya existe y no puede ser modificado", dni);
				
				throw new ServiceException(mensaje);
			}
		
			Cliente cliente = this.getClienteExistente(dni);
			
			if(cliente == null) {
				cliente = new Cliente();
				
				cliente.setDni(dni);
				cliente.setNombre(nombre);
				
				this.repositorioClientes.saveOrUpdate(cliente);
			}
			
			Socio newSocio = new Socio();
			
			newSocio.setCliente(cliente);
			newSocio.setFechaNacimiento(fechaNac);
			newSocio.setDomicilio(domicilio);
			newSocio.setTelefono(telefono);
			newSocio.setEmail(email);
			
			this.repositorioSocios.saveOrUpdate(newSocio);
			
			Ficha newFicha = new Ficha();
			
			newFicha.setSocio(newSocio);
			newFicha.setActivo(true);
			newFicha.setAprobada(true);
			
			this.repositorioCuentas.saveOrUpdate(newFicha);
		} catch (RepositoryException e) {
			throw new ServiceException(e);
		}
	}
	
	private Cliente getClienteExistente(String dni) throws RepositoryException {
		String queryExpression = "from Cliente c where c.dni = :dni";
		QueryParameter parameter = new QueryParameter("dni", dni);
		Cliente cliente = this.repositorioClientes.get(queryExpression, parameter);
		
		return cliente;
	}
	
	private Socio getSocioExistente(String dni) throws RepositoryException {
		String queryExpression = "from Socio s where s.cliente.dni = :dni";
		QueryParameter parameter = new QueryParameter("dni", dni);
		Socio socio = this.repositorioSocios.get(queryExpression, parameter);
		
		return socio;
	}
}
